<?php
/**
 * 话题帖子搜索
 *
 * SearchTopic.class.php
 * Created by IntelliJ IDEA.
 *
 * @author: hjh <hjh@jf.com>
 *
 * Date: 2017/10/26
 * Time: 21:25
 */

namespace Search;

use Circle\Topic;
use Circle\TopicContent;
use Recommend\HotRank;

class SearchTopic extends SearchBase
{
    public static $QUEUE_NAME = 'SearchTopic';
    public static $SEARCH_INDEX = self::TOPIC_SEARCH;

    const FIELD_TOPIC_ID = 'topicid';
    const FIELD_USER_ID = 'userid';
    const FIELD_CIRCLE_ID = 'circleid';
    const FIELD_TITLE = 'title';
    const FIELD_DESCRIPTION = 'description';
    const FIELD_COVERS = 'covers';
    const FIELD_IMG_COUNT = 'imgcount';
    const FIELD_VIEW_COUNT = 'viewcount';
    const FIELD_LIKE_COUNT = 'likecount';
    const FIELD_COMMENT_COUNT = 'commentcount';
    const FIELD_SHARE_COUNT = 'sharecount';
    const FIELD_DISLIKE_COUNT = 'dislikecount';
    const FIELD_HOT_SCORE = 'hotscore';
    const FIELD_IS_TOP = 'istop';
    const FIELD_STATUS = 'status';
    const FIELD_UPDATE_TIME = 'updatetime';
    const FIELD_CREATE_TIME = 'createtime';
    const FIELD_CONTENT = 'content';

    const SORT_FIELD_UPDATE_TIME = self::FIELD_UPDATE_TIME;
    const SORT_FIELD_CREATE_TIME = self::FIELD_CREATE_TIME;
    const SORT_FIELD_HOT_SCORE = self::FIELD_HOT_SCORE;
    const SORT_FIELD_IS_TOP = self::FIELD_IS_TOP;

    public static $SEARCH_FIELD_MAP = [
        Topic::FIELD_TOPIC_ID => [self::FIELD_TOPIC_ID, self::FIELD_DATA_TYPE_INT],
        Topic::FIELD_USER_ID => [self::FIELD_USER_ID, self::FIELD_DATA_TYPE_INT],
        Topic::FIELD_CIRCLE_ID => [self::FIELD_CIRCLE_ID, self::FIELD_DATA_TYPE_INT],
        Topic::FIELD_TITLE => [self::FIELD_TITLE, self::FIELD_DATA_TYPE_STRING],
        Topic::FIELD_DESCRIPTION => [self::FIELD_DESCRIPTION, self::FIELD_DATA_TYPE_STRING],
        Topic::FIELD_COVERS => [self::FIELD_COVERS, self::FIELD_DATA_TYPE_ARRAY],
        Topic::FIELD_IMG_COUNT => [self::FIELD_IMG_COUNT, self::FIELD_DATA_TYPE_INT],
        Topic::FIELD_VIEW_COUNT => [self::FIELD_VIEW_COUNT, self::FIELD_DATA_TYPE_INT],
        Topic::FIELD_LIKE_COUNT => [self::FIELD_LIKE_COUNT, self::FIELD_DATA_TYPE_INT],
        Topic::FIELD_COMMENT_COUNT => [self::FIELD_COMMENT_COUNT, self::FIELD_DATA_TYPE_INT],
        Topic::FIELD_SHARE_COUNT => [self::FIELD_SHARE_COUNT, self::FIELD_DATA_TYPE_INT],
        Topic::FIELD_DISLIKE_COUNT => [self::FIELD_DISLIKE_COUNT, self::FIELD_DATA_TYPE_INT],
        Topic::FIELD_HOT_SCORE => [self::FIELD_HOT_SCORE, self::FIELD_DATA_TYPE_DOUBLE],
        Topic::FIELD_IS_TOP => [self::FIELD_IS_TOP, self::FIELD_DATA_TYPE_INT],
        Topic::FIELD_STATUS => [self::FIELD_STATUS, self::FIELD_DATA_TYPE_INT],
        Topic::FIELD_UPDATE_TIME => [self::FIELD_UPDATE_TIME, self::FIELD_DATA_TYPE_DATE],
        Topic::FIELD_CREATE_TIME => [self::FIELD_CREATE_TIME, self::FIELD_DATA_TYPE_DATE],
        TopicContent::FIELD_CONTENT => [self::FIELD_CONTENT, self::FIELD_DATA_TYPE_STRING]
    ];

    /**
     * @see SearchBase::Add($id, $info)     新增
     * @see SearchBase::update($id, $info)  更新
     */

    /**
     * 格式化 添加搜索的数据
     *
     * @param $id
     * @param $info
     * @return array|bool
     */
    public static function formatAddData($id, $info)
    {
        if (!isset($info[Topic::FIELD_HOT_SCORE])) {
            $info[Topic::FIELD_HOT_SCORE] = HotRank::score($info[Topic::FIELD_VIEW_COUNT],
                $info[Topic::FIELD_LIKE_COUNT], $info[Topic::FIELD_DISLIKE_COUNT], $info[Topic::FIELD_SHARE_COUNT],
                $info[Topic::FIELD_COMMENT_COUNT], $info[Topic::FIELD_UPDATE_TIME]);
        }

        if (!isset($info[TopicContent::FIELD_CONTENT])) {
            $topicContent = TopicContent::getInfoByIds($info[Topic::FIELD_TOPIC_ID]);
            if (!isset($topicContent[TopicContent::FIELD_CONTENT])) {
                debug_log("SearchTopic formatAddData failed, not found content", JF_LOG_ERROR);

                return false;
            }
            $info[TopicContent::FIELD_CONTENT] = json_decode($topicContent[TopicContent::FIELD_CONTENT],
                JSON_UNESCAPED_UNICODE);

            usleep(50 * 1000);
        }

        $diffKey = array_diff_key(static::$SEARCH_FIELD_MAP, $info);
        if (count($diffKey) > 0) {
            debug_log(['formatAddData ', $diffKey], JF_LOG_ERROR);

            return false;
        }
        $data = [self::FIELD_ID => $id];
        foreach (static::$SEARCH_FIELD_MAP as $key => $value) {
            $data[$value[0]] = self::formatData($value[1], $info[$key]);
        }

        return $data;
    }

    /**
     * @param int   $offset
     * @param int   $limit
     * @param array $fields          需要返回那些字段，默认全部返回
     * @param array $excludeTopicIds 需要排除的主题ID
     * @param int   $status          获取那种状态，默认是正常的
     * @return array
     */
    public static function searchHotTopics(
        $offset = 0,
        $limit = 10,
        $fields = [],
        $excludeTopicIds = [],
        $status = Topic::STATUS_NORMAL
    ) {
        if (empty($fields)) {
            $fields = self::buildAllFields();
        }
        $query = [
            "query" => [
                "bool" => [
                    "must" => [
                        "term" => [
                            "status" => $status
                        ]
                    ]
                ]
            ],
            "sort" => [
                self::FIELD_HOT_SCORE => [
                    "order" => "desc"
                ]
            ],
            "_source" => $fields,
            "from" => $offset,
            "size" => $limit
        ];

        if (count($excludeTopicIds) > 0) {
            $query['query']['bool']['must_not'] = [
                "terms" => [
                    self::FIELD_TOPIC_ID => $excludeTopicIds
                ]
            ];
        }

        return self::getSearchResults($query, $fields);
    }

    /**
     * @param array $userIds        用户ID列表
     * @param array $circleIds      圈子ID列表
     * @param int   $offset         偏移起始未知
     * @param int   $limit          每页条数
     * @param array $fields         返回的字段书
     * @param array $sort           排序
     * @param array $sort           排序
     * @param array $excludeUserIds 排除用户编号
     * @return array
     */
    public static function searchTopicsByUserIdsOrCircleIds(
        $userIds,
        $circleIds,
        $offset = 0,
        $limit = 10,
        $fields = [],
        $sort = [],
        $status = Topic::STATUS_NORMAL,
        $excludeUserIds = []
    ) {
        if (empty($fields)) {
            $fields = self::buildAllFields();
        }
        if (empty($sort)) {
            $sort = [
                self::SORT_FIELD_CREATE_TIME => [
                    'order' => self::SORT_TYPE_DESC
                ]
            ];
        }
        $query = [
            "query" => [
                "bool" => [
                    "must" => [
                        "term" => [
                            self::FIELD_STATUS => $status,
                        ]
                    ],
                    "should" => [
                        [
                            "terms" => [
                                self::FIELD_USER_ID => $userIds
                            ]
                        ],
                        [
                            "terms" => [
                                self::FIELD_CIRCLE_ID => $circleIds
                            ]
                        ]
                    ],
                    "minimum_number_should_match" => 1
                ]
            ],
            "sort" => $sort,
            "_source" => $fields,
            "from" => $offset,
            "size" => $limit,
        ];

        if (count($excludeUserIds) > 0) {
            $query["query"]["bool"]["must_not"] = [
                "terms" => [
                    self::FIELD_USER_ID => $excludeUserIds,
                ]
            ];
        }

        return self::getSearchResults($query, $fields);
    }

    /**
     * 根据圈子Id搜索帖子
     *
     * @param int   $circleId
     * @param int   $offset
     * @param int   $limit
     * @param array $fields
     * @param array $sort
     * @param int   $status
     * @return array
     */
    public static function searchTopicsByCircleId(
        $circleId,
        $offset = 0,
        $limit = 10,
        $fields = [],
        $sort = [],
        $status = Topic::STATUS_NORMAL
    ) {
        if (empty($fields)) {
            $fields = self::buildAllFields();
        }
        if (empty($sort)) {
            $sort = [
                self::SORT_FIELD_IS_TOP => ['order' => self::SORT_TYPE_DESC],
                self::SORT_FIELD_CREATE_TIME => ['order' => self::SORT_TYPE_DESC]
            ];
        }
        $query = [
            "query" => [
                "bool" => [
                    "must" => [
                        [
                            "term" => [
                                self::FIELD_CIRCLE_ID => $circleId
                            ]
                        ],
                        [
                            "term" => [
                                self::FIELD_STATUS => $status,
                            ]
                        ]
                    ]
                ]
            ],
            "sort" => $sort,
            "_source" => $fields,
            "from" => $offset,
            "size" => $limit,
        ];

        return self::getSearchResults($query, $fields);
    }

    /**
     * 根据圈子Id搜索置顶帖子或除去置顶数据的帖子
     *
     * @param int       $circleId
     * @param int|array $istop 1：置顶数据 array:除去的帖子id数组
     * @param int       $offset
     * @param int       $limit
     * @param array     $fields
     * @param array     $sort
     * @param array     $status
     * @return array
     */
    public static function searchTopTopicsByCircleId(
        $circleId,
        $istop = 0,
        $offset = 0,
        $limit = 10,
        $fields = [],
        $sort = [],
        $status = [Topic::STATUS_NORMAL]
    ) {
        if (empty($fields)) {
            $fields = self::buildAllFields();
        }
        if (empty($sort)) {
            $sort = [
                self::SORT_FIELD_CREATE_TIME => ['order' => self::SORT_TYPE_DESC]
            ];
        }
        if ($istop == 1) {
            $status = [Topic::STATUS_NORMAL, Topic::STATUS_RULES];
        }
        $query = [
            "query" => [
                "bool" => [
                    "must" => [
                        [
                            "term" => [
                                self::FIELD_CIRCLE_ID => $circleId
                            ]
                        ],
                        [
                            "terms" => [
                                self::FIELD_STATUS => $status,
                            ]
                        ]
                    ]
                ]
            ],
            "sort" => $sort,
            "_source" => $fields,
            "from" => $offset,
            "size" => $limit,
        ];
        if ($istop == 1) {
            $query['query']['bool']['must'][] = [
                "term" => [
                    self::FIELD_IS_TOP => 1
                ]
            ];
        }
        if (is_array($istop) && !empty($istop)) {
            $query['query']['bool']['must_not'][] = [
                "terms" => [
                    self::FIELD_TOPIC_ID => $istop
                ]
            ];
        }

        return self::getSearchResults($query, $fields);
    }

    /**
     * 构造全部返回字段
     *
     * @return array
     */
    protected static function buildAllFields()
    {
        return [
            self::FIELD_TOPIC_ID,
            self::FIELD_USER_ID,
            self::FIELD_CIRCLE_ID,
            self::FIELD_TITLE,
            self::FIELD_DESCRIPTION,
            self::FIELD_COVERS,
            self::FIELD_IMG_COUNT,
            self::FIELD_VIEW_COUNT,
            self::FIELD_LIKE_COUNT,
            self::FIELD_COMMENT_COUNT,
            self::FIELD_SHARE_COUNT,
            self::FIELD_DISLIKE_COUNT,
            self::FIELD_HOT_SCORE,
            self::FIELD_IS_TOP,
            self::FIELD_STATUS,
            self::FIELD_UPDATE_TIME,
            self::FIELD_CREATE_TIME
        ];
    }
}

